import os
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QDateEdit, QVBoxLayout, QComboBox, \
    QColorDialog, QFontDialog, QSlider, QLineEdit, QGridLayout, QCheckBox, QMessageBox, QRadioButton
from PyQt5.QtCore import QTimer, Qt, QDateTime, QPoint
from PyQt5.QtGui import QColor, QFont, QIcon
import datetime

class CountdownTimer(QWidget):
    ########################################################
    # 初始主题为 'light' 或 'dark'
    CURRENT_THEME_NAME = 'light'
    ICO_APP_URL = 'res/app.ico'
    ICO_EXIT_URL = 'res/ico/exit.png'
    ICO_START_TIME_URL = 'res/ico/start_time.png'
    ICO_STICKY_URL = 'res/ico/sticky.png'
    ICO_COLOR_URL = 'res/ico/color.png'
    ICO_FONT_URL = 'res/ico/font.png'
    ICO_THEME_URL = 'res/ico/theme.png'
    ICO_SOFTWARE_INFO_URL = 'res/ico/software_info.png'
    SOFTWARE_INFO_BG_LOGO = 'res/ico/fxxw.ico'
    SOFTWARE_VERSION_NO = '240618R1'
    SOFTWARE_RELEASE_DATE = '24年6月18日'
    DEFAULT_APP_FONT_NAME = '楷体'
    DEFAULT_FONT_COLOR = '#EC407A'  # 倒计时标签默认颜色
    DEFAULT_FONT_SIZE = 32
    DEFAULT_FONT_NAME = 'Consolas'  # 默认字体 Arial Consolas
    ALWAYS_ON_TOP_FLG = False
    STICKY_NOTE_RATE = 2  # 便签缩小比例  原始的/2
    ########################################################

    def __init__(self):
        super().__init__()
        self.screen_width = self.screen().size().width()
        self.screen_height = self.screen().size().height()
        self.dragging = False  # 标记是否正在拖动窗口
        self.lastMousePosition = QPoint(0, 0)  # 上一次鼠标位置
        self.isDarkMode = False  # 添加这个标志位，默认为False非暗黑模式
        self.init_ui()
        self.current_theme = self.CURRENT_THEME_NAME
        # 初始设置 全局的变量
        self.color = QColor(self.DEFAULT_FONT_COLOR)
        self.font = QFont(self.DEFAULT_FONT_NAME, self.DEFAULT_FONT_SIZE)
        self.opacity = 100
        self.is_sticky_note = False
        self.apply_theme()  # 默认应用浅色主题 dark light 可以切换主题配色 False
        self.original_geometry = self.geometry()

    def init_ui(self):
        self.setWindowTitle(f'日程倒计时@佛系小吴{self.SOFTWARE_VERSION_NO}')
        # 第一个参数 (100): 窗口左上角距离屏幕左边缘的水平像素距离。
        # 第二个参数 (100): 窗口左上角距离屏幕顶部边缘的垂直像素距离。
        # 第三个参数 (320): 窗口的宽度，即窗口左右边缘之间的像素距离。
        # 第四个参数 (180): 窗口的高度，即窗口上下边缘之间的像素距离。
        self.setGeometry(320, 320, 448, 320)
        self.setWindowIcon(QIcon(self.get_resource_path('res/app.ico')))
        # 垂直布局 软件结构主要布局
        main_layout = QVBoxLayout()
        # 使用网格布局来优化按钮布局
        button_layout = QGridLayout()

        # 日期选择器
        self.date_picker = QDateEdit(calendarPopup=True)
        # 最少为当前天的时间
        self.date_picker.setMinimumDate(datetime.date.today())
        self.date_picker.setDateTime(datetime.datetime.now())
        # 字体选择按钮
        self.font_button = QPushButton('选择字体')
        self.font_button.setIcon(QIcon(self.get_resource_path(self.ICO_FONT_URL)))
        self.font_button.clicked.connect(self.choose_countdown_label_font)
        # 颜色选择按钮
        self.color_button = QPushButton('选择颜色')
        self.color_button.setIcon(QIcon(self.get_resource_path(self.ICO_COLOR_URL)))
        self.color_button.clicked.connect(self.choose_countdown_label_color)
        button_layout.addWidget(self.date_picker, 0, 0, 1, 2)
        button_layout.addWidget(self.font_button, 0, 3)
        button_layout.addWidget(self.color_button, 0, 4)

        # 字体大小滑动条
        self.font_size_label = QLabel('字体大小')
        button_layout.addWidget(self.font_size_label, 1, 0)
        self.font_size_slider = QSlider(Qt.Horizontal)
        self.font_size_slider.setRange(15, 185)
        self.font_size_slider.setValue(10)
        self.font_size_slider.valueChanged.connect(self.slider_update_countdown_label_font_size)
        # 将font_size_slider添加到button_layout中，从第2列开始，跨越2列
        # 第一个1表示行跨度，第二个2表示列跨度
        button_layout.addWidget(self.font_size_slider, 1, 1)

        # 添加文字说明标签
        self.opacity_label = QLabel('透 明 度')
        # 在第0行第1列添加按钮
        button_layout.addWidget(self.opacity_label, 1, 3)
        self.opacity_slider = QSlider(Qt.Horizontal)
        self.opacity_slider.setRange(20, 100)
        self.opacity_slider.setValue(100)
        self.opacity_slider.valueChanged.connect(self.slider_update_countdown_label_opacity)
        button_layout.addWidget(self.opacity_slider, 1, 4)

        # 倒计时文字说明编辑框
        self.description_label = QLabel('输入计时文字描述:')
        button_layout.addWidget(self.description_label, 2, 0, 1, 2)
        self.description_edit = QLineEdit()
        self.description_edit.setText('*距离XX仅*')
        button_layout.addWidget(self.description_edit, 2, 3, 1, 2)

        self.always_on_top_button = QRadioButton('始终置顶', self)
        button_layout.addWidget(self.always_on_top_button, 3, 0)
        self.always_on_top_button.clicked.connect(self.set_always_on_top)
        # 一键切换主题按钮
        self.toggle_theme_button = QPushButton('主题')
        self.toggle_theme_button.setIcon(QIcon(self.get_resource_path(self.ICO_THEME_URL)))
        self.toggle_theme_button.clicked.connect(self.toggle_theme)
        button_layout.addWidget(self.toggle_theme_button, 3, 1)  # 跨越4列
        # 开机自启动单选按钮
        self.auto_start_checkbox = QCheckBox('开机自启')
        button_layout.addWidget(self.auto_start_checkbox, 3, 3, 1, 1)
        self.software_info_button = QPushButton('软件信息')
        self.software_info_button.setIcon(QIcon(self.get_resource_path(self.ICO_SOFTWARE_INFO_URL)))
        self.software_info_button.clicked.connect(self.show_software_info)
        button_layout.addWidget(self.software_info_button, 3, 4)  # 跨越4列

        # 将网格布局添加到主布局中
        main_layout.addLayout(button_layout)

        # 开始倒计时按钮
        self.start_button = QPushButton('开始计时')
        self.start_button.clicked.connect(self.start_count_down)
        self.start_button.setIcon(QIcon(self.get_resource_path(self.ICO_START_TIME_URL)))
        button_layout.addWidget(self.start_button, 4, 0, 1, 2)
        # 以便签的形式显示按钮
        self.sticky_note_button = QPushButton('便签模式')
        self.sticky_note_button.clicked.connect(self.show_as_sticky_note)
        self.sticky_note_button.setIcon(QIcon(self.get_resource_path(self.ICO_STICKY_URL)))
        button_layout.addWidget(self.sticky_note_button, 4, 3)
        # 添加退出便签显示按钮
        self.exit_sticky_button = QPushButton('')
        self.exit_sticky_button.clicked.connect(self.exit_sticky_note)  # 连接槽函数
        self.exit_sticky_button.setIcon(QIcon(self.get_resource_path(self.ICO_EXIT_URL)))
        button_layout.addWidget(self.exit_sticky_button, 4, 4)  # 添加到布局
        self.exit_sticky_button.hide()

        # 倒计时显示标签
        self.countdown_label = QLabel("00天00时00分00秒", self)
        # 优化倒计时标签的样式，设置字体大小、颜色和加粗
        self.countdown_label.setAlignment(Qt.AlignCenter)  # 水平和垂直居中对齐
        self.countdown_label.setObjectName('label_time')
        main_layout.addWidget(self.countdown_label)

        # 开始定时器 时间倒计时
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_count_down)
        self.setLayout(main_layout)

    # 设置置顶逻辑
    def set_always_on_top(self):
        # ALWAYS_ON_TOP_FLG 默认为 False
        if self.ALWAYS_ON_TOP_FLG:
            #  置顶 --> 普通
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.always_on_top_button.setText('普通窗口')
            self.show()
        else:
            # 普通 -> 置顶
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.always_on_top_button.setText('始终置顶')
            self.show()
        self.ALWAYS_ON_TOP_FLG = not self.ALWAYS_ON_TOP_FLG

    # 获取单文件exe资源路径 解决打包bug
    def get_resource_path(self, relative_path):
        try:
            base_path = sys._MEIPASS
        except AttributeError:
            base_path = os.path.abspath(".")
        dest_path = os.path.join(base_path, relative_path)
        return dest_path

    # 选择字体按钮的控制功能
    def choose_countdown_label_font(self):
        font, ok = QFontDialog.getFont(self.font)
        if ok:
            # 将字体信息存储到全局变量 Font 对象里面
            self.font = font
            self.countdown_label.setFont(self.font)
            self.update_countdown_label_ui()

    # 选择颜色按钮的控制
    def choose_countdown_label_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.color = color
            # 更新countdown_label样式
            self.update_countdown_label_ui()

    def show_software_info(self):
        software_info_base = """
        <html><head><style>
          .title {{font-size: 24px; font-weight: bold;}}.author {{font-size: 18px;color: #1E88E5;}}
          .description {{font-size: 15px;}}.image {{margin: 0 0 5px 5px;border: 1px solid #ddd;}}
        </style></head><body><div class="title">软件名称</div><div class="author">作者：@佛系小吴</div><div class="description"><p>软件简介:一个日程倒计时软件</p><p>版本信息:{}</p><p>发布日期：{}</p>
        <div><img class="image" src="{}"/></div>
        </div></body></html>
        """
        software_info_text = software_info_base.format(self.SOFTWARE_VERSION_NO, self.SOFTWARE_RELEASE_DATE, self.get_resource_path(self.SOFTWARE_INFO_BG_LOGO))
        # 显示消息框
        QMessageBox.information(self, "软件信息", software_info_text)

    # 把函数抽象出来成为一个公共方法 变量都是全局的可以优化
    def update_countdown_label_ui(self):
        # 修改颜色的同时仍要保持原有的字体大小以及样式
        countdown_label_style_css = f"color: {self.color.name()}; color: {self.color.name()}; font-family: {self.font.family()};font-size: {self.font.pointSize()}px;"
        print('** 当前更新的样式为 %s ' % countdown_label_style_css)
        self.countdown_label.setStyleSheet(countdown_label_style_css)
        self.setWindowOpacity(self.opacity / 100.0)

    # 滑动条控制字体大小
    def slider_update_countdown_label_font_size(self, value):
        self.font.setPointSize(value)
        print('== 字体滑动条大小: %s px == ' % value)
        self.update_countdown_label_ui()

    # 调整窗体的透明度
    def slider_update_countdown_label_opacity(self, value):
        self.opacity = value
        print('== 透明度滑动条大小: %s == ' % value)
        self.setWindowOpacity(self.opacity / 100.0)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.dragging = True
            self.lastMousePosition = event.globalPos() - self.pos()  # 计算偏移量

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton and self.dragging:
            self.move(event.globalPos() - self.lastMousePosition)  # 更新窗口位置

    def mouseReleaseEvent(self, event):
        self.dragging = False

    def toggle_theme(self):
        """
        切换应用的主题模式。
        """
        self.isDarkMode = not self.isDarkMode
        self.apply_theme()

    def apply_theme(self):
        """
        应用指定的主题到界面元素上。
        :param theme: 'dark' 或 'light'，分别代表深色和亮色主题。
        """
        styleSheetBase = """
            QWidget {{
                font-family: {};
                background-color: {}; /* 主背景颜色 */
                color: {}; /* 文字颜色 */
            }}
            QCheckBox  {{
                border-radius: 10px; /* 设置复选框圆角 */
            }}
            QSlider  {{
                border-radius: 10px; /* 设置滑动条圆角 */
            }}
            QPushButton  {{
                border-radius: 20px; /* 设置按钮圆角 */
                padding: 5px; /* 按钮内边距 */
            }}
            QRadioButton {{
                border-radius: 10px; /* 设置圆角 */
                color: #E74C3C; /* #EC7063设置文字颜色 #333333*/
                background-color: #f0f0f0; /* 设置背景颜色 */
            }}
            QRadioButton::indicator {{
                border: 1px solid #aaaaaa; /* 设置指示器边框颜色 */
                border-radius: 10px; /* 设置指示器圆角 */
                width: 15px; /* 设置指示器宽度 */
                height: 15px; /* 设置指示器高度 */
            }}
            QRadioButton::indicator:unchecked {{
                background-color: #ffffff; /* 设置未选中时的背景颜色 */
            }}
            QRadioButton::indicator:checked {{
                background-color: #8E44AD; /* #5555ff设置选中时的背景颜色 */
            }}
            QLabel{{
                font-size:20px;
                font-weight: bold; /* 加粗 */
                color: #EC407A; /* #EC407A 水红#EC407A 蓝色#3F51B5 #26A69A 红橙色 #FF4500 深粉红色 #FF1493 间宝石绿 #66CDAA 青色#009ad6 */
                font-family: {}; /* "Arial"、"Helvetica"、"Times" 、"Consolas" */
            }}
            QLabel#label_time {{
                font-size: {}px;
                background-color: {}; /* 时间标签背景颜色 */
                font-weight: bold; /* 加粗 */
                color: {}; /* #EC407A 水红#EC407A 蓝色#3F51B5 #26A69A 红橙色 #FF4500 深粉红色 #FF1493 间宝石绿 #66CDAA 青色#009ad6 */
                font-family: 'Consolas'; /* "Arial"、"Helvetica"、"Times" 、"Consolas" */
            }}
            QPushButton {{
                border: 1px solid {}; /* 按钮边框颜色 */
                border-radius: 10px;
                padding: 5px;
                margin: 2px;
            }}
            QPushButton:hover {{
                border-color: {}; /* 按钮鼠标悬停边框颜色 */
            }}
            QPushButton:pressed {{
                background-color: {}; /* 按钮按下时背景颜色 */
            }}
        """
        if self.isDarkMode:
            # 主背景颜色   文字颜色 字体大小 时间标签背景颜色  时间标签文字颜色 按钮边框颜色 按钮鼠标悬停边框颜色 按钮按下时背景颜色
            style_sheet_css = styleSheetBase.format(self.DEFAULT_APP_FONT_NAME, '#333333', '#FFFFFF', self.DEFAULT_APP_FONT_NAME,self.DEFAULT_FONT_SIZE, '#424242', self.DEFAULT_FONT_COLOR, '#4CAF50', '#E41188', '#2E7D32')
        else:  # 默认为亮色主题
            style_sheet_css = styleSheetBase.format(self.DEFAULT_APP_FONT_NAME, '#FFFFFF', '#000000', self.DEFAULT_APP_FONT_NAME,self.DEFAULT_FONT_SIZE, '#F0FFF0', self.DEFAULT_FONT_COLOR, '#AAAAAA', '#4CAF50', '#E41188')
        self.setStyleSheet(style_sheet_css)

    # 点击开始倒计时
    def start_count_down(self):
        # 获取用户选择的日期
        target_pick_date = self.date_picker.date()
        # 00:00:00 获取目标日期 设置为 午夜00:00:00
        target_datetime = QDateTime(target_pick_date).toPyDateTime().replace(hour=0, minute=0, second=0, microsecond=0)
        # 获取当前时间的日期部分 软件点击时间算起
        current_datetime = QDateTime(datetime.datetime.now())  # 将当前时间转换为
        # 计算两个时间点之间的差异（目标时间点 - 当前时间点）
        if target_datetime <= current_datetime.toPyDateTime():
            QMessageBox.warning(self, '提示', '请检查日期！')
            return
        # 计算剩余的秒数
        self.seconds_to_target = int((target_datetime - current_datetime.toPyDateTime()).total_seconds())
        # 初始化倒计时的天、小时、分钟和秒
        self.days, remainder = divmod(self.seconds_to_target, 86400)
        self.hours, remainder = divmod(remainder, 3600)
        self.minutes, self.seconds = divmod(remainder, 60)

        # 更新倒计时标签并启动定时器
        self.update_count_down()
        self.timer.start(1000)  # 每秒更新一次

    # fix bug 0619 时间倒计时分钟数不自减
    def update_count_down(self):
        SECONDS_PER_MINUTE = 60
        SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60
        # 减少秒数，并根据需要减少分钟、小时和天数
        self.seconds -= 1
        if self.seconds < 0:
            # 减少到0的时候显示 59s
            self.seconds = SECONDS_PER_MINUTE - 1
            # 分钟数 -1
            self.minutes -= 1
            # 分钟数减少到0的时候 分钟数置为59
            if self.minutes < 0:
                self.minutes = SECONDS_PER_MINUTE - 1
                # 时 -1
                self.hours -= 1
                if self.hours < 0:
                    self.hours = SECONDS_PER_HOUR - 1
                    self.days -= 1
        # 检查倒计时是否完成
        if self.days < 0:
            self.timer.stop()  # 停止定时器
            QMessageBox.information(self, '完成', '倒计时结束！')
            return
        # 使用f-string格式化时间字符串
        time_str = f"{self.days}天{self.hours:02d}时{self.minutes:02d}分{self.seconds:02d}秒"
        description = self.description_edit.text().strip()
        if description:
            time_str = f"{description}\n{time_str}"
        # 更新倒计时标签
        self.countdown_label.setText(time_str)

    # 退出便签模式 True 转为 False
    def exit_sticky_note(self):
        # 如果是True 就是退出逻辑  False就是提示
        if self.is_sticky_note:
            # 恢复窗口到原始大小和位置
            self.setGeometry(self.original_geometry)
            # 显示所有之前隐藏的控件
            self.date_picker.show()
            self.font_button.show()
            self.color_button.show()
            self.opacity_slider.show()
            self.description_label.show()
            self.auto_start_checkbox.show()
            self.toggle_theme_button.show()
            self.software_info_button.show()
            self.sticky_note_button.show()
            self.start_button.show()
            self.date_picker.show()
            self.font_size_label.show()
            self.opacity_label.show()
            self.description_edit.show()
            self.font_size_slider.show()
            self.always_on_top_button.show()
            # 退出便签按钮 隐藏
            self.exit_sticky_button.hide()
            # 重置窗口的透明度
            self.opacity_slider.setValue(100)
            self.setWindowOpacity(1.0)  # 窗口完全不透明
            # 将状态设置为 非便签模式
            self.is_sticky_note = not self.is_sticky_note
            # 显示窗口标题栏
            self.showNormal()
            # 退出置顶时
            # 重置窗口标志以显示标题栏和其他窗口装饰
            self.setWindowFlags(self.windowFlags() & ~Qt.FramelessWindowHint)
            self.show()

    def show_as_sticky_note(self):
        # 1.不是便签模式 2.设置为Ture便签模式
        self.is_sticky_note = not self.is_sticky_note
        if self.is_sticky_note:
            # 便签模式下的业务逻辑
            self.date_picker.hide()
            self.font_button.hide()
            self.color_button.hide()
            self.opacity_slider.hide()
            self.description_label.hide()
            self.auto_start_checkbox.hide()
            self.toggle_theme_button.hide()
            self.software_info_button.hide()
            self.sticky_note_button.hide()
            self.start_button.hide()
            self.date_picker.hide()
            self.font_size_label.hide()
            self.opacity_label.hide()
            self.description_edit.hide()
            self.font_size_slider.hide()
            self.always_on_top_button.hide()
            # 退出便签按钮 显示出来
            self.exit_sticky_button.show()
            # 移动窗口到右上角，并调整大小 调节透明度 y 应该就是10
            resize_width = int(round(self.width()/self.STICKY_NOTE_RATE))
            resize_height = int(round(self.height() / self.STICKY_NOTE_RATE))
            self.setGeometry(self.screen_width - self.width() - 30,
                             self.screen_height - self.height() - 65, resize_width
                             , resize_height)
            # 设置窗口的属性，使其没有边框和标题栏
            self.setWindowFlags(Qt.FramelessWindowHint)
            # 刷新窗体显示
            self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    countdown_timer = CountdownTimer()
    countdown_timer.show()
    sys.exit(app.exec_())